package com.winter.main.config;

import com.winter.main.constant.SystemConstant;
import com.winter.main.model.entity.SysRole;
import com.winter.main.model.entity.SysRule;
import com.winter.main.model.entity.SysUser;
import com.winter.main.service.system.SysRoleService;
import com.winter.main.service.system.SysRuleService;
import com.winter.main.service.system.SysUserService;
import com.winter.main.utils.MD5Util;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * Desc: 用户验证,条件过滤
 * Author: dushuang
 * Date: Create in 2018/4/26
 */
public class CustomRealm extends AuthorizingRealm{

    @Autowired
    //shiro和cache在引用service实例顺序问题，shiro引入应在cache后(不然这几个service的缓存不生效)
    @Lazy
    private SysUserService userService;

    @Autowired
    @Lazy
    private SysRoleService roleService;

    @Autowired
    @Lazy
    private SysRuleService ruleService;

    /**
     * 角色和对应权限添加
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取登录用户名
        String username = (String)principalCollection.getPrimaryPrincipal();
        // 查询用户信息
        SysUser user = userService.findByUsername(username);
        // 添加角色和权限
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        try {
            List<SysRole> roles = roleService.selectRoleByUser(user);
            for (SysRole role : roles){
                authorizationInfo.addRole(role.getRoleCode());
            }
            List<SysRule> rules = ruleService.selectRuleByUser(user);
            for (SysRule rule : rules){
                authorizationInfo.addStringPermission(rule.getRuleCode());
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return authorizationInfo;
    }

    /**
     * 用户认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证，然后在到请求
        if(authenticationToken.getPrincipal() == null){
            return null;
        }
        // 放入key,通过md5(password+key)验证
        if(SecurityUtils.getSubject() == null || SecurityUtils.getSubject().getSession().getAttribute(SystemConstant.USER_KEY) == null){
            throw new IncorrectCredentialsException();
        }
        // 获取用户名
        String username = authenticationToken.getPrincipal().toString();
        SysUser user = userService.findByUsername(username);
        if(user == null){
            return null;
        }else{
            if(user.getStatus() != 1){
                throw new LockedAccountException();
            }
            // salt
            String key = SecurityUtils.getSubject().getSession().getAttribute(SystemConstant.USER_KEY).toString();
            SimpleAuthenticationInfo authenticationInfo = null;
            try {
                authenticationInfo = new SimpleAuthenticationInfo(
                        username,MD5Util.md5(user.getPassword()+key),getName());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return authenticationInfo;
        }
    }
}
